package tech.waterism.topo.iterator;

import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import tech.waterism.topo.model.TopoNode;

import java.util.*;

import static org.junit.jupiter.api.Assertions.*;

/**
 * TopologyIterator 单元测试
 * 
 * @author waterism
 * @since 1.0.0
 */
class TopologyIteratorTest {
    
    private List<TopoNode> nodes;
    
    @BeforeEach
    void setUp() {
        nodes = new ArrayList<>();
        for (int i = 0; i < 5; i++) {
            TopoNode node = new TopoNode();
            node.setStcd("NODE" + i);
            node.setStnm("节点" + i);
            nodes.add(node);
        }
    }
    
    @Test
    void testHasNext_InitialState() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 初始状态应该有下一个元素
        assertTrue(iterator.hasNext());
    }
    
    @Test
    void testNext_SequentialAccess() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 顺序访问所有节点
        for (int i = 0; i < 5; i++) {
            assertTrue(iterator.hasNext());
            TopoNode node = iterator.next();
            assertNotNull(node);
            assertEquals("NODE" + i, node.getStcd());
        }
        
        // 访问完所有节点后，hasNext应该返回false
        assertFalse(iterator.hasNext());
    }
    
    @Test
    void testNext_ThrowsException_WhenNoMore() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 访问所有节点
        for (int i = 0; i < 5; i++) {
            iterator.next();
        }
        
        // 尝试访问更多节点应该抛出异常
        assertThrows(NoSuchElementException.class, iterator::next);
    }
    
    @Test
    void testGetCurrentIndex() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 初始索引应该是0
        assertEquals(0, iterator.getCurrentIndex());
        
        // 访问一个节点后，索引应该是1
        iterator.next();
        assertEquals(1, iterator.getCurrentIndex());
        
        // 访问两个节点后，索引应该是2
        iterator.next();
        assertEquals(2, iterator.getCurrentIndex());
    }
    
    @Test
    void testMarkBacktrackPoint_AndBacktrack() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 访问两个节点
        iterator.next(); // NODE0
        iterator.next(); // NODE1
        assertEquals(2, iterator.getCurrentIndex());
        
        // 标记回溯点
        iterator.markBacktrackPoint();
        
        // 继续访问
        iterator.next(); // NODE2
        iterator.next(); // NODE3
        assertEquals(4, iterator.getCurrentIndex());
        
        // 回溯
        iterator.backtrack();
        assertEquals(2, iterator.getCurrentIndex());
        
        // 下一个应该是NODE2
        TopoNode node = iterator.next();
        assertEquals("NODE2", node.getStcd());
    }
    
    @Test
    void testBacktrackTo_SpecificPosition() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 访问到索引3
        for (int i = 0; i < 3; i++) {
            iterator.next();
        }
        assertEquals(3, iterator.getCurrentIndex());
        
        // 回溯到索引1
        iterator.backtrackTo(1);
        assertEquals(1, iterator.getCurrentIndex());
        
        // 下一个应该是NODE1
        TopoNode node = iterator.next();
        assertEquals("NODE1", node.getStcd());
    }
    
    @Test
    void testBacktrackTo_InvalidIndex() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 回溯到负数索引（应该不改变当前位置）
        iterator.backtrackTo(-1);
        assertEquals(0, iterator.getCurrentIndex());
        
        // 回溯到超出范围的索引（应该不改变当前位置）
        iterator.backtrackTo(100);
        assertEquals(0, iterator.getCurrentIndex());
    }
    
    @Test
    void testJumpTo() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 跳到索引3
        iterator.jumpTo(3);
        assertEquals(3, iterator.getCurrentIndex());
        
        // 下一个应该是NODE3
        TopoNode node = iterator.next();
        assertEquals("NODE3", node.getStcd());
    }
    
    @Test
    void testJumpTo_EndOfList() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 跳到列表末尾
        iterator.jumpTo(5);
        assertEquals(5, iterator.getCurrentIndex());
        
        // 应该没有下一个元素
        assertFalse(iterator.hasNext());
    }
    
    @Test
    void testSize() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 大小应该是5
        assertEquals(5, iterator.size());
    }
    
    @Test
    void testReset() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 访问几个节点
        iterator.next();
        iterator.next();
        iterator.markBacktrackPoint();
        iterator.next();
        
        assertEquals(3, iterator.getCurrentIndex());
        
        // 重置
        iterator.reset();
        
        // 应该回到起始状态
        assertEquals(0, iterator.getCurrentIndex());
        assertTrue(iterator.hasNext());
        
        // 下一个应该是NODE0
        TopoNode node = iterator.next();
        assertEquals("NODE0", node.getStcd());
    }
    
    @Test
    void testGet() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 获取索引2的节点
        TopoNode node = iterator.get(2);
        assertNotNull(node);
        assertEquals("NODE2", node.getStcd());
        
        // 当前索引不应该改变
        assertEquals(0, iterator.getCurrentIndex());
    }
    
    @Test
    void testGet_InvalidIndex() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 获取无效索引应该抛出异常
        assertThrows(IndexOutOfBoundsException.class, () -> iterator.get(-1));
        assertThrows(IndexOutOfBoundsException.class, () -> iterator.get(10));
    }
    
    @Test
    void testEmptyList() {
        TopologyIterator iterator = new TopologyIterator(new ArrayList<>());
        
        // 空列表
        assertFalse(iterator.hasNext());
        assertEquals(0, iterator.size());
        assertThrows(NoSuchElementException.class, iterator::next);
    }
    
    @Test
    void testNullList() {
        TopologyIterator iterator = new TopologyIterator(null);
        
        // null列表应该被处理为空列表
        assertFalse(iterator.hasNext());
        assertEquals(0, iterator.size());
    }
    
    @Test
    void testMultipleBacktrack() {
        TopologyIterator iterator = new TopologyIterator(nodes);
        
        // 第一个回溯点
        iterator.next(); // 0
        iterator.markBacktrackPoint(); // mark at 1
        
        iterator.next(); // 1
        iterator.next(); // 2
        iterator.markBacktrackPoint(); // mark at 3
        
        iterator.next(); // 3
        iterator.next(); // 4
        
        // 回溯到索引3
        iterator.backtrack();
        assertEquals(3, iterator.getCurrentIndex());
        
        // 再次回溯到索引1
        iterator.backtrack();
        assertEquals(1, iterator.getCurrentIndex());
    }
}

